package com.newsnetwork.api.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @author: HuangDekai
 * @date: 2022/11/6 0:28
 * @version: 1.0
 * @since: jdk8
 * @description: 使用AOP, 获取 service 的日志及其执行时间, 对其执行进行监控
 */
@Aspect
@Component
public class ServiceLogAspect {
    public static final Logger log = LoggerFactory.getLogger(ServiceLogAspect.class);

    private static final Long ERROR_TIMEOUT = 3000L;
    private static final Long WARN_TIMEOUT = 2000L;


    /**
     * 环绕的方法为:
     * execution(* com.newsnetwork.*.service.impl..*.*(..))
     *           *                                          环绕的方法的返回类型为所有返回类型
     *             com.newsnetwork.*.service.impl..         ..代表当前包及所有子包
     *                                             *.*      第一个*匹配某个类类名, .代表当前类的某个方法, 后一个*代表方法名
     *                                                (..)  代表方法的参数列表为任意参数, 即可以是有参数, 也可以使任意参数
     *
     * @param joinPoint 切入点, 可以获得织入的方法的属性(如方法名, 参数列表)
     * @return joinPoint.proceed()
     */
    @Around("execution(* com.newsnetwork.*.service.impl..*.*(..))")
    public Object recordTimeOfService(ProceedingJoinPoint joinPoint) throws Throwable {
        //打印织入的方法的 类名.方法名
        log.info("=============== 开始执行 {}.{} ===============",
                joinPoint.getTarget().getClass(),
                joinPoint.getSignature().getName());

        long start = System.currentTimeMillis();

        // 环绕方法, 代表方法正常执行
        Object result = joinPoint.proceed();

        //方法执行完后
        long end = System.currentTimeMillis();
        long takeTime = end - start;

        if (takeTime > ERROR_TIMEOUT) {
            log.error("当前执行耗时: {}", takeTime);
        } else if (takeTime > WARN_TIMEOUT) {
            log.warn("当前执行耗时: {}", takeTime);
        } else {
            log.info("当前执行耗时: {}", takeTime);
        }

        return result;
    }
}
